#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>


void strtok_break_string(void)
{
    printf("***** strtok_break_string *****\n");
    int toknum = 0;
    char src[] = "Hello,, world!";
    const char delimiters[] = ", !";
    char *token = strtok(src, delimiters);
    while (token != NULL)
    {
        printf("%d: [%s]\n", ++toknum, token);
        // Calls to strtok to continue tokenizing the same source string should not pass the source string again, 
        // but instead pass NULL as the first argument.
        token = strtok(NULL, delimiters);
    }
    /* source is now "Hello\0, world\0\0" */
}

void string_const(void)
{
    printf("***** string_const *****\n");
    // char *string = "hello world";
    // printf("string: %s\n", string);
    // string = "123";
    // printf("string: %s\n", string);

    char const * string = "hello world";
    printf("string: %s\n", string);
    string = "123";
    printf("string: %s\n", string);

    char modifiable_string[] = "hello world";
    printf("modifiable_string: %s\n", modifiable_string);
    // This is equivalent to the following:
    char modifiable_string_1[] = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0'};
    printf("modifiable_string_1: %s\n", modifiable_string_1);
}

void copying_string(void)
{
    /*
    You can use the = operator to copy integers, 
    but you cannot use the = operator to copy strings in C. 
    Strings in C are represented as arrays of characters with a terminating null-character, 
    so using the = operator will only save the address (pointer) of a string.
    */
    printf("***** copying_string *****\n");
    int a = 10, b;
    char c[] = "abc", *d;
    b = a; /* Integer is copied */
    a = 20; /* Modifying a leaves b unchanged - b is a 'deep copy' of a */
    printf("%d %d\n", a, b); /* "20 10" will be printed */
    
    d = c;
    /* Only copies the address of the string -
    there is still only one string stored in memory */
    c[1] = 'x';
    /* Modifies the original string - d[1] = 'x' will do exactly the same thing */
    printf("%s %s\n", c, d); /* "axc axc" will be printed */

}

// The above example compiled because we used char *d rather than char d[3]. 

void copying_string_compile_error(void)
{
    printf("***** copying_string_compile_error *****\n");
    char a[] = "abc";
    char b[8];
    //  error: assignment to expression with array type
    // b = a; /* compile error */
    printf("%s\n", b);
}

void copying_string_strcpy(void)
{
    printf("***** copying_string_strcpy *****\n");
    // Enough space must be allocated for the destination before copying.
    char a[] = "abc";
    char b[8];
    strcpy(b, a); /* think "b special equals a" */
    printf("b: %s\n", b); /* "abc" will be printed */
}


void copying_string_snprintf(void)
{
    printf("***** copying_string_snprintf *****\n");
    char a[] = "012345678901234567890";
    char b[8];
    #if 0
        strcpy(b, a); /* causes buffer overrun (undefined behavior), so do not execute this here! */
    #endif

    snprintf(b, sizeof(b), "%s", a); /* does not cause buffer overrun */
    // strcpy(b, a);
    printf("%s\n", b); /* "0123456" will be printed */
}


void concatenating_string_strncat(void)
{
    printf("***** concatenating_string_strncat *****\n");
    char source[] = "contatenating string";
    char dest[32];
    dest[0] = '\0';
    strncat(dest,source, sizeof(dest)-1);
    /* copies up to the first (sizeof(dest) - 1) elements of source into dest,
    then puts a \0 on the end of dest */
    printf("dest: %s\n", dest);
}


void copying_string_strncpy(void)
{
    printf("***** copying_string_strncpy *****\n");
    char a[8] = "0123456";
    char b[32];
    strncpy(b, a, sizeof(b)); /* the third parameter is destination buffer size */
    b[sizeof(b)/sizeof(*b) - 1] = '\0'; /* terminate the string */
    printf("%s\n", b); /* "0123456" will be printed */
}

int main(void)
{
    strtok_break_string();
    string_const();
    copying_string();
    copying_string_compile_error();
    copying_string_strcpy();
    copying_string_snprintf();
    concatenating_string_strncat();
    copying_string_strncpy();
    system("pause");
}



/*
In C, a string is not an intrinsic type.

A C-string is the convention to have a one-dimensional array of characters
which is terminated by a null-character, by a '\0'.

This means that a C-string with a content of "abc" will have four characters 'a', 'b', 'c' and '\0'.


*/